package com.hsmpay.yl8583.service;

import com.hsmpay.utils.DesUtil;
import com.hsmpay.utils.WriteFile;
import com.hsmpay.yl8583.utils.TestDes;
import com.iso8583.Iso8583Composer;
import com.iso8583.Iso8583Parser;
import com.iso8583.util.ByteUtils;
import com.iso8583.util.J8583Util;
import com.iso8583.util.PosUtil;
import org.apache.commons.lang.StringUtils;

import java.util.HashMap;
import java.util.Map;

public class KaYinKaSocketToBoss {

    static WriteFile wf = new WriteFile("ds_kayinka");
    static String ipAddr = "118.145.0.117";
    static Integer iPort = 10020;
    static String organizationId = "160007";
    String itimeout = "60000";
    String ShopCode = "838416834238753";//商户号
    String PosNo = "22639560";//终端号
    String tpdu = "6000050000";//tpdu
    String header = "603100311004";//header
    String batch = "000001";// 批次号
    String operator = "001";//操作员
    String PinKey = "";
    //封顶密文报文密钥
    String MacKey = "";
    //母POS密钥
    String MasterKey = "8AE4C4710F8A50FE";
    /**
     * 构造函数
     *
     * @param ShopCode
     * @param PosNo
     * @param batch
     * @param MasterKey
     * @param PinKey
     * @param MacKey
     * @param trkKey
     */
    public KaYinKaSocketToBoss(String ShopCode, String PosNo, String batch, String MasterKey, String PinKey, String MacKey, String trkKey, Map<String,String> config) {
        if (null != config){
            this.ipAddr = config.containsKey("ip") ? config.get("ip") : "";
            String port = config.containsKey("port") ? config.get("port") : "";
            if (StringUtils.isNotBlank(port)){
                this.iPort = Integer.valueOf(port);
            }
            this.organizationId = config.containsKey("organizationId") ? config.get("organizationId") : "160007";
        }
        this.ShopCode = ShopCode;
        this.PosNo = PosNo;
        this.batch = batch;
        this.MasterKey = MasterKey;
        this.PinKey = PinKey;
        this.MacKey = MacKey;
        if (null != batch && StringUtils.isEmpty(batch.trim())) {
            this.batch = "000001";
        }
        wf.log("tpdu:" + this.tpdu, "调试");
        wf.log("ShopCode(商户号):" + this.ShopCode, "调试");
        wf.log("PosNo(终端号):" + this.PosNo, "调试");
        wf.log("batch(批次号):" + this.batch, "调试");
        wf.log("MasterKey:" + this.MasterKey, "调试");
        wf.log("PinKey:" + this.PinKey, "调试");
        wf.log("MacKey:" + this.MacKey, "调试");
    }
    /**
     * 终端签到
     * @return 批次号
     * @throws Exception
     */
    public String Login0800(String serialNumber) throws Exception {
        String LoginMsg = "";
        String TYPE_ID = "0800";
        String mustFields = "";
        HashMap<String,String> body = new HashMap<String,String>();
        wf.log("-------------------请求包域值信息-------------------", "调试");
        body.put("TPDU", this.tpdu);
        body.put("HEAD", this.header);
        //11 41 42 44域
        body.put("CSEQ_NO", serialNumber);
        body.put("F31", this.organizationId);
        body.put("TRM_NO", this.PosNo);
        body.put("MERC_CD", this.ShopCode);
        //body.put("ADD_DATA", channelId);//44域,渠道id
        body.put("RESE_PRI_60", "00" + batch + "0010");
        body.put("RESE_PRI_63","001");
        String optionalFields = "11|31|41|42|60|63";
        //生成报文
        System.out.println("卡银卡签到生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optionalFields, TYPE_ID, body, "kayinka", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage, false);//此处false代表加不加空格
        wf.log("卡银卡签到请求报文为：" + req, "调试");
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, this.ipAddr, this.iPort);
        String res = ByteUtils.byte2HexStr(response, false);
        wf.log("卡银卡签到响应报文为：" + res, "调试");
        try {
            //解析报文
            byte[] bytes = ByteUtils.hexStringToByte(res);
            Map<String, String> map = Iso8583Parser.parse("KAYINKA", bytes, true);
            //处理解析的map
            //分别获取39,60,62域
            String bit39 = map.get("39");
            if ("00".equals(bit39)){
                String bit60 = map.get("60");
                String bit62 = map.get("62");
                if (StringUtils.isBlank(bit60)) {
                    bit60 = "000001";
                }else{
                    bit60 = bit60.substring(2,8);
                }
                //62域,含PIK、MAK共40字节
                if (StringUtils.isBlank(bit62)){
                    LoginMsg = "-1_";
                }else if (bit62.length() != 48){
                    LoginMsg = "-1_";
                }else {
                    String PIK = bit62.substring(0, 16);
                    String PIK_CHECKVALUE = bit62.substring(16, 24);
                    String MAK = bit62.substring(24, 40);
                    String MAK_CHECKVALUE = bit62.substring(40);
                    String decodedPIK = DesUtil.decodc(PIK, this.MasterKey);
                    String decodedMAK = DesUtil.decodc(MAK, this.MasterKey);
                    String PIK_CHECK = DesUtil.encodc("0000000000000000", decodedPIK).substring(0, 8);
                    String MAK_CHECK = DesUtil.encodc("0000000000000000", decodedMAK).substring(0, 8);
                    System.out.println("PIK_CHECKVALUE:" + PIK_CHECKVALUE + "\tPIK_CHECK:" + PIK_CHECK + "\tPIK校验结果为: " + PIK_CHECKVALUE.equals(PIK_CHECK));
                    System.out.println("MAK_CHECKVALUE:" + MAK_CHECKVALUE + "\tMAK_CHECK:" + MAK_CHECK + "\tMAK校验结果为: " + MAK_CHECKVALUE.equals(MAK_CHECK));
                    LoginMsg = "0_" + bit39 + "_" + bit60 + "_" + PIK + "_" + MAK;
                }
            }else{
                LoginMsg = "-1_";
                wf.log("卡银卡签到请求返回响应吗为：" + bit39, "调试");
            }
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("卡银卡签到返回报文解析报文错误");

        }
        return LoginMsg;
    }
    /**
     * 消费
     *
     * @param trk2          二磁道数据
     * @param trk3          三磁道数据
     * @param pin           密码
     * @param money         交易金额
     * @param accountNumber 卡号
     * @param serialNumber  订单号
     * @param bit23         IC卡序列号
     * @param bit55         IC卡 55 域
     * @param bit14         IC卡 序列号
     * @return 返回消费相关信息
     * @throws Exception
     */
    public String BillPayment(String trk2, String trk3, String pin, String money, String accountNumber, String serialNumber, String bit23, String bit55, String bit14) throws Exception {
        String des_pin = TestDes.MakeDesPin(accountNumber, pin, this.PinKey, MasterKey);
        String comsumeMsg = "";
        String TYPE_ID = "0200";
        String mustFields = "";
        StringBuffer optionalFields = new StringBuffer("");
        HashMap<String,String> body = new HashMap<String,String>();
        body.put("TPDU", this.tpdu);
        body.put("HEAD", this.header);
        //3 4 11 22 25 26 35 36 41 42 44 4 49 52
        body.put("PAN", accountNumber);
        optionalFields.append("2|");
        body.put("PRO_COD", "000000");
        optionalFields.append("3|");
        body.put("TTXN_AMT", money);
        optionalFields.append("4|");
        body.put("CSEQ_NO", serialNumber);
        optionalFields.append("11|");
        if (!"".equals(bit14.trim())) {
            body.put("EXP_DT", bit14);
            optionalFields.append("14|");
        }
        if ("".equals(bit55.trim())) {
            body.put("IN_MOD", "021");
            optionalFields.append("22|");
        }else {
            body.put("IN_MOD", "051");
            optionalFields.append("22|");
        }
        if (!"".equals(bit23.trim())) {
            body.put("SEP_NUM", bit23);
            optionalFields.append("23|");
        }
        body.put("CON_MOD", "00");
        optionalFields.append("25|");
        body.put("PIN_CAP_CODE", "06");
        optionalFields.append("26|");
        body.put("F31", this.organizationId);
        optionalFields.append("31|");

        if (!"".equals(trk2.trim())) {
            body.put("TRACK_2", trk2);
            optionalFields.append("35|");
        }
        if (!"".equals(trk3.trim())) {
            body.put("TRACK_3", trk3);
            optionalFields.append("36|");
        }
        body.put("TRM_NO", this.PosNo);
        optionalFields.append("41|");
        body.put("MERC_CD", this.ShopCode);
        optionalFields.append("42|");
        body.put("CCY", "156");
        optionalFields.append("49|");
        body.put("PIN_DATA", des_pin);
        optionalFields.append("52|");
        body.put("SECUR_INF", "2000000000000000");
        optionalFields.append("53|");
        if (!"".equals(bit55.trim())) {
            body.put("IC_DAT", bit55);
            optionalFields.append("55|");
        }
        if ("".equals(bit55.trim())) {
            body.put("RESE_PRI_60", "22" + this.batch + "000");
            optionalFields.append("60|");
        }else {
            body.put("RESE_PRI_60", "22" + this.batch + "00050");
            optionalFields.append("60|");
        }
        optionalFields.append("64");
        body.put("F64","");
        Iso8583Composer com = new Iso8583Composer();
        byte[] MacMessage = com.compose(mustFields, optionalFields.toString(), TYPE_ID, body, "kayinka", true);
        String request = ByteUtils.byte2HexStr(MacMessage,false);
        String sub = request.substring(22, request.length()-16);
        //63域是否要出现
        String macstr = TestDes.MakeKaYinKaECBMac(this.MacKey, sub, this.MasterKey);//加密操作,传参问题
        body.put("F64", macstr);
        System.out.println("optionalFields " + optionalFields.toString());
        //生成报文
        System.out.println("卡银卡消费生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optionalFields.toString(), TYPE_ID, body, "kayinka", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        PosUtil.parse8583("kayinka",req.substring(4));//解析请求报文

        System.out.println("卡银卡消费请求报文为：" + req);
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, this.ipAddr, this.iPort);
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("卡银卡消费响应报文是：" + res);
        try {
            PosUtil.parse8583("kayinka", res);
            //解析报文,返回解析的域map
            Map<String, String> map = Iso8583Parser.parse("kayinka", response, true);
            //需要获取2,4,11,12,13,14,37,38,39域信息
            String result2 = map.get("2");
            String result4 = map.get("4");
            String result11 = map.get("11");
            String result12 = map.get("12");
            String result13 = map.get("13");
            String result14 = map.get("14");
            String result37 = map.get("37");
            String result38 = map.get("38");
            String result39 = map.get("39");
            comsumeMsg = "0_" + result2 + "_" +result4 + "_" +result11 + "_" + result12 + "_" +result13 + "_" + result14 + "_" +result37 + "_" +result38 +"_"+result39;
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("卡银卡消费响应报文解析错误");

        }
        return comsumeMsg;
    }

    /**
     * 消费冲正（交易）
     * @return 订单信息
     * @throws Exception
     */
    public String unBillPayment(String money,String accountNumber,String serialNumber,String bit39,String bit38,String bit23,String bit55,String bit14) throws Exception {

        String comsumeMsg = "";
        String TYPE_ID = "0400";
        String mustFields = "";
        StringBuffer optionalFields = new StringBuffer("");
        HashMap<String,String> body = new HashMap<String,String>();
        body.put("TPDU", this.tpdu);
        body.put("HEAD", this.header);
        //3 4 11 22 25 26 35 36 41 42 44 4 49 52
        body.put("PAN", accountNumber);
        optionalFields.append("2|");
        body.put("PRO_COD", "000000");
        optionalFields.append("3|");
        body.put("TTXN_AMT", money);
        optionalFields.append("4|");
        body.put("CSEQ_NO", serialNumber);
        optionalFields.append("11|");
        if (!"".equals(bit14.trim())) {
            body.put("EXP_DT", bit14);
            optionalFields.append("14|");
        }
        if ("".equals(bit55.trim())) {
            body.put("IN_MOD", "021");
            optionalFields.append("22|");
        }else {
            body.put("IN_MOD", "051");
            optionalFields.append("22|");
        }
        if (!"".equals(bit23.trim())) {
            body.put("SEP_NUM", bit23);
            optionalFields.append("23|");
        }
        body.put("CON_MOD", "00");
        optionalFields.append("25|");
        body.put("F31", this.organizationId);
        optionalFields.append("31|");
        body.put("CPSCOD", bit39);
        optionalFields.append("39|");
        body.put("TRM_NO", this.PosNo);
        optionalFields.append("41|");
        body.put("MERC_CD", this.ShopCode);
        optionalFields.append("42|");
        body.put("CCY", "156");
        optionalFields.append("49|");
        if (!"".equals(bit55.trim())) {
            body.put("IC_DAT", bit55);
            optionalFields.append("55|");
        }
        if ("".equals(bit55.trim())) {
            body.put("RESE_PRI_60", "22" + this.batch + "000");
            optionalFields.append("60|");
        }else {
            body.put("RESE_PRI_60", "22" + this.batch + "00050");
            optionalFields.append("60|");
        }
        optionalFields.append("64");
        body.put("F64","");
        Iso8583Composer com = new Iso8583Composer();
        byte[] MacMessage = com.compose(mustFields, optionalFields.toString(), TYPE_ID, body, "kayinka", true);
        String request = ByteUtils.byte2HexStr(MacMessage,false);
        String sub = request.substring(22, request.length()-16);
        //63域是否要出现
        String macstr = TestDes.MakeKaYinKaECBMac(this.MacKey, sub, this.MasterKey);//加密操作,传参问题
        body.put("F64", macstr);
        System.out.println("optionalFields " + optionalFields.toString());
        //生成报文
        System.out.println("卡银卡撤销生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optionalFields.toString(), TYPE_ID, body, "kayinka", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        PosUtil.parse8583("kayinka",req.substring(4));//解析请求报文

        System.out.println("卡银卡撤销请求报文为：" + req);
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, this.ipAddr, this.iPort);
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("卡银卡撤销响应报文是：" + res);
        try {
            PosUtil.parse8583("kayinka", res);
            //解析报文,返回解析的域map
            Map<String, String> map = Iso8583Parser.parse("kayinka", response, true);
            String temp2 = map.get("2");
            String temp4 = map.get("4");
            String temp11 = map.get("11");
            String temp12 = map.get("12");
            String temp13 = map.get("13");
            String temp14 = map.get("14");
            String temp37 = map.get("37");
            String temp38 = map.get("38");
            String temp39 = map.get("39");
            String temp44 = map.get("44");
            String temp61 = map.get("61");
            comsumeMsg = temp2+"_"+temp4+"_"+temp11+"_"+temp12+"_"+temp13+"_"+temp14+"_"+temp37+"_"+temp38+"_"+temp39+"_"+temp44+"_"+temp61;
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("卡银卡撤销响应报文解析错误");
        }
        wf.log("卡银卡消费冲正返回数据:" + comsumeMsg, "调试");
        return comsumeMsg;
    }
}
